﻿using LightCAD.Core;
using LightCAD.Core.Elements;
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static LightCAD.Runtime.Constants;

namespace LightCAD.Runtime
{
    using System.Diagnostics;

    public class ViewportRenderer
    {
        private DocumentRuntime docRt;
        private ViewportRuntime vportRt;

        public double Zoom = 1.0;

        public Box2d WorldScope;
        public SKRect ScrScope;

        public float OriginX = 100;
        public float OriginY = 100;


        public ViewportRenderer(DocumentRuntime docRt, ViewportRuntime vportRt)
        {
            this.docRt = docRt;
            this.vportRt = vportRt;
        }
        /// <summary>
        /// 根据世界坐标起点，在屏幕上绘制长度固定的直线，用于坐标系、光标绘制
        /// </summary>
        /// <param name="canvas"></param>
        /// <param name="toScr">WcsToScr或UcsToScr</param>
        /// <param name="start"></param>
        /// <param name="dir"></param>
        /// <param name="scrLength"></param>
        public void DrawLine(SKCanvas canvas, SKPaint paint, Matrix3d toScr, Vector2d start, Vector2d dir, double scrLength)
        {
            var wcsLength = scrLength / this.vportRt.Viewport.Scale;
            var end = start + dir * wcsLength;
            var scrStart = toScr.MultiplyPoint(start);
            var scrEnd = toScr.MultiplyPoint(end);
            canvas.DrawLine(scrStart.ToSKPoint(), scrEnd.ToSKPoint(), paint);
        }

        /// <summary>
        /// 根据世界坐标起点，终点坐标绘制直线
        /// </summary>
        /// <param name="canvas"></param>
        /// <param name="toScr">WcsToScr或UcsToScr</param>
        /// <param name="start"></param>
        /// <param name="dir"></param>
        /// <param name="scrLength"></param>
        public void DrawLine(SKCanvas canvas, SKPaint paint, Matrix3d toScr, Vector2d start, Vector2d end)
        {
            var scrStart = toScr.MultiplyPoint(start);
            var scrEnd = toScr.MultiplyPoint(end);
            canvas.DrawLine(scrStart.ToSKPoint(), scrEnd.ToSKPoint(), paint);
        }
        /// <summary>
        /// 根据世界坐标中心点，在屏幕上绘制长宽固定的矩形，用于坐标系、光标绘制
        /// </summary>
        /// <param name="canvas"></param>
        /// <param name="toScr">WcsToScr或UcsToScr</param>
        /// <param name="wcsCenter"></param>
        /// <param name="wcsWidth"></param>
        /// <param name="wcsHeight"></param>
        public void DrawRect(SKCanvas canvas, SKPaint paint, Matrix3d toScr, Vector2d wcsCenter, double scrWidth, double scrHeight)
        {
            var wcsWidth = scrWidth / this.vportRt.Viewport.Scale;
            var wcsHeight = scrHeight / this.vportRt.Viewport.Scale;

            var wcsLeftBottom = wcsCenter + new Vector2d(-wcsWidth / 2, -wcsHeight / 2);
            var scrLeftBottom = toScr.MultiplyPoint(wcsLeftBottom).ToSKPoint();

            var wcsLeftTop = wcsCenter + new Vector2d(-wcsWidth / 2, wcsHeight / 2);
            var scrLeftTop = toScr.MultiplyPoint(wcsLeftTop).ToSKPoint();

            var wcsRightTop = wcsCenter + new Vector2d(wcsWidth / 2, wcsHeight / 2);
            var scrRightTop = toScr.MultiplyPoint(wcsRightTop).ToSKPoint();

            var wcsRightBottom = wcsCenter + new Vector2d(wcsWidth / 2, -wcsHeight / 2);
            var scrRightBottom = toScr.MultiplyPoint(wcsRightBottom).ToSKPoint();

            canvas.DrawLine(scrLeftBottom, scrLeftTop, paint);
            canvas.DrawLine(scrLeftTop, scrRightTop, paint);
            canvas.DrawLine(scrRightTop, scrRightBottom, paint);
            canvas.DrawLine(scrRightBottom, scrLeftBottom, paint);

        }
        public void DrawOriginAxis(SKCanvas canvas)
        {
            var vp = this.vportRt.Viewport;
            using (var paint = new SKPaint { Color = OriginAxisColor, IsStroke = true })
            {
                var toScr = this.vportRt.WcsToScr;
                DrawRect(canvas, paint, toScr, Vector2d.Zero, OriginSize, OriginSize);
                DrawLine(canvas, paint, toScr, Vector2d.Zero, Vector2d.UnitX, OriginLength);
                DrawLine(canvas, paint, toScr, Vector2d.Zero, Vector2d.UnitY, OriginLength);
            }
        }
        public void DrawGrid(SKCanvas canvas)
        {
            using (var g_paint = new SKPaint { Color = GridColor, IsStroke = true })
            using (var ay_paint = new SKPaint { Color = AxisYColor, IsStroke = true })
            using (var ax_paint = new SKPaint { Color = AxisXColor, IsStroke = true })
            using (var sg_paint = new SKPaint { Color = SubGridColor, IsStroke = true })
            {
                //绘制竖向Grid 原点左边
                var idx = 0;
                while (OriginX - idx * GridSize * GridRatio > 0)
                {
                    var x = OriginX - idx * GridSize * GridRatio;
                    if (x == OriginX)
                    {
                        //绘制Y正轴
                        canvas.DrawLine(x, 0, x, (float)vportRt.Viewport.Height - OriginY, ay_paint);
                        //负轴方向绘制Grid
                        canvas.DrawLine(x, (float)vportRt.Viewport.Height - OriginY, x, (float)vportRt.Viewport.Height, g_paint);
                    }
                    else
                    {
                        if (idx % 5 == 0)
                            canvas.DrawLine(x, 0, x, (float)vportRt.Viewport.Height - 1, g_paint);
                        else
                            canvas.DrawLine(x, 0, x, (float)vportRt.Viewport.Height - 1, sg_paint);
                    }
                    idx++;
                }

                //绘制竖向Grid 原点右边
                idx = 0;
                while (OriginX + idx * GridSize * GridRatio <= vportRt.Viewport.Width - 1)
                {
                    var x = OriginX + idx * GridSize * GridRatio;
                    if (x == OriginX)
                    {
                        idx++;
                        continue;
                    }
                    else
                    {
                        if (idx % 5 == 0)
                            canvas.DrawLine(x, 0, x, (float)vportRt.Viewport.Height - 1, g_paint);//绘制主网格
                        else
                            canvas.DrawLine(x, 0, x, (float)vportRt.Viewport.Height - 1, sg_paint);//绘制次网格
                    }
                    idx++;
                }

                var oY = vportRt.Viewport.Height - OriginY;
                //绘制横向Grid 原点上边
                idx = 0;
                while (oY - idx * GridSize * GridRatio > 0)
                {
                    var y = oY - idx * GridSize * GridRatio;
                    if (y == oY)
                    {
                        //绘制X正轴
                        canvas.DrawLine(OriginX, (float)oY, (float)vportRt.Viewport.Width - 1, (float)oY, ax_paint);
                        //负轴方向绘制Grid
                        canvas.DrawLine(0, (float)oY, OriginX, (float)oY, g_paint);
                    }
                    else
                    {
                        if (idx % 5 == 0)
                            canvas.DrawLine(0, (float)y, (float)vportRt.Viewport.Width - 1, (float)y, g_paint);//绘制主网格
                        else
                            canvas.DrawLine(0, (float)y, (float)vportRt.Viewport.Width - 1, (float)y, sg_paint);//绘制次网格
                    }
                    idx++;
                }

                //绘制横向Grid 原点下面
                idx = 0;
                while (oY + idx * GridSize * GridRatio <= vportRt.Viewport.Height - 1)
                {
                    var y = oY + idx * GridSize * GridRatio;
                    if (y == oY)
                    {
                        idx++;
                        continue;
                    }
                    else
                    {
                        if (idx % 5 == 0)
                            canvas.DrawLine(0, (float)y, (float)vportRt.Viewport.Width - 1, (float)y, g_paint);
                        else
                            canvas.DrawLine(0, (float)y, (float)vportRt.Viewport.Width - 1, (float)y, sg_paint);
                    }
                    idx++;
                }
            }
        }


        public void DrawCrossCursor(SKCanvas canvas, LcCursorType cursorType, CursorAddonType CursorAddon = CursorAddonType.None)
        {
            var p = vportRt.PointerMovedPosition;
            using (var paint = new SKPaint { Color = SKColors.White, IsStroke = true })
            {
                Matrix3d toScr = this.vportRt.IsUcsOpened ? this.vportRt.UcsToScr : this.vportRt.WcsToScr;
                Matrix3d fromScr = this.vportRt.IsUcsOpened ? this.vportRt.ScrToUcs : this.vportRt.ScrToWcs;
                var curp = fromScr.MultiplyPoint(p.ToVector2d());

                if (cursorType == LcCursorType.SelectElement
                    || cursorType == LcCursorType.InputPoint)
                {
                    var curSize = CursorCrossSize / this.vportRt.Viewport.Scale;
                    DrawLine(canvas, paint, toScr, curp + Vector2d.UnitX * (-curSize / 2), curp + Vector2d.UnitX * (curSize / 2));
                    DrawLine(canvas, paint, toScr, curp + Vector2d.UnitY * (-curSize / 2), curp + Vector2d.UnitY * (curSize / 2));
                }

                if (cursorType == LcCursorType.SelectElement
                    || cursorType == LcCursorType.InputElement)
                {
                    DrawRect(canvas, paint, toScr, curp, SelectBoxSize, SelectBoxSize);
                }

                if (CursorAddon == CursorAddonType.Plus)
                {
                    var curAddonSize = CursorAddonSize / this.vportRt.Viewport.Scale;
                    var ap = new Vector2d(curp.X + curAddonSize * 2, curp.Y + curAddonSize * 2);
                    DrawLine(canvas, paint, toScr, ap + Vector2d.UnitX * (-curAddonSize / 2), Vector2d.UnitX, curAddonSize);
                    DrawLine(canvas, paint, toScr, ap + Vector2d.UnitY * (-curAddonSize / 2), Vector2d.UnitY, curAddonSize);
                }
            }
        }


        public void DrawSelectRect(SKCanvas canvas, SKPoint from, SKPoint to)
        {
            if (from == to) return;
            if (from.X > to.X)
            {
                DrawSelectRectCrossed(canvas, from, to);
            }
            else
            {
                DrawSelectRectIncluded(canvas, from, to);
            }
        }
        public void DrawSelectRectIncluded(SKCanvas canvas, SKPoint from, SKPoint to)
        {
            using (var fillColor = new SKPaint { Color = SelectRectFillColor_Included, IsStroke = false })
            using (var penColor = new SKPaint { Color = SKColors.White, IsStroke = true })
            {
                var x = from.X;
                var y = Math.Min(from.Y, to.Y);
                var w = Math.Abs(to.X - from.X);
                var h = Math.Abs(to.Y - from.Y);
                canvas.DrawRect(x, y, w, h, fillColor);
                canvas.DrawRect(x, y, w, h, penColor);
            }
        }
        public void DrawSelectRectCrossed(SKCanvas canvas, SKPoint from, SKPoint to)
        {
            using (var fillColor = new SKPaint { Color = SelectRectFillColor_Crossed, IsStroke = false })
            using (var penColor = new SKPaint
            {
                Color = SKColors.White,
                IsStroke = true,
                PathEffect = SKPathEffect.CreateDash(new float[] { 5, 5 }, 20)
            })
            {
                var x = Math.Min(from.X, to.X);
                var y = Math.Min(from.Y, to.Y);
                var w = Math.Abs(to.X - from.X);
                var h = Math.Abs(to.Y - from.Y);
                canvas.DrawRect(x, y, w, h, fillColor);
                canvas.DrawRect(x, y, w, h, penColor);
            }
        }

        internal void Clear(SKCanvas canvas)
        {
            canvas.Clear(Background);
        }


        public double ScrToWorld(float length)
        {
            var zoom = ScrScope.Width / WorldScope.Width;
            return (1 / zoom) * length;
        }
        public Vector2d ScrToWorld(SKPoint sp)
        {
            var sptmp = new Vector2d(sp.X, ScrScope.Height - sp.Y);
            var zoom = ScrScope.Width / WorldScope.Width;
            var wptmp = (1 / zoom) * sptmp;
            var mt = Matrix3d.Translate(WorldScope.Location);
            var wp = mt * wptmp;
            return wp;

        }
        public float WorldToScr(double length)
        {
            var zoom = ScrScope.Width / WorldScope.Width;
            return (float)(zoom * length);
        }
        public SKPoint WorldToScr(Vector2d wp)
        {
            //var matrix = WorldToScrMatrix();
            //return matrix.MapPoint((float)wp.X,(float)wp.Y);

            var mt = Matrix3d.Translate(WorldScope.Location).Inverse();
            var tptmp = mt * wp;
            var zoom = ScrScope.Width / WorldScope.Width;
            var sptmp = (zoom * tptmp);
            var sp = new SKPoint((float)sptmp.X, (float)(ScrScope.Height - sptmp.Y));
            return sp;
        }

        internal void DrawUcsIcon(SKCanvas canvas)
        {
            var vp = this.vportRt.Viewport;
            using (var paintO = new SKPaint { Color = OriginAxisColor, IsStroke = true })
            {
                using (var paintX = new SKPaint { Color = AxisXColor, IsStroke = true })
                {
                    using (var paintY = new SKPaint { Color = AxisYColor, IsStroke = true })
                    {
                        var toScr = this.vportRt.UcsToScr;
                        DrawRect(canvas, paintO, toScr, Vector2d.Zero, OriginSize, OriginSize);
                        DrawLine(canvas, paintX, toScr, Vector2d.Zero, Vector2d.UnitX, OriginLength);
                        DrawLine(canvas, paintY, toScr, Vector2d.Zero, Vector2d.UnitY, OriginLength);



                        //var sc = this.vportRt.WcsToScr.MultiplyPoint(vp.Ucs.Origin);
                        //var scp = sc.ToSKPoint();
                        //canvas.DrawCircle(scp, OriginSize/2, paintO);//TODO:正方形

                        //var sx = vp.Ucs.XAxis* OriginLength/vp.Scale + vp.Ucs.Origin;
                        //var sy = vp.Ucs.YAxis * OriginLength/ vp.Scale + vp.Ucs.Origin;
                        //var sxp = this.vportRt.WcsToScr.MultiplyPoint(sx);
                        //var syp = this.vportRt.WcsToScr.MultiplyPoint(sy);

                        //canvas.DrawLine(scp, sxp.ToSKPoint(), paintX);
                        //canvas.DrawLine(scp, syp.ToSKPoint(), paintY);
                    }
                }
            }
        }

        public Box2d GetWcsClipBox()
        {
            LcViewport vp = this.vportRt.Viewport;
            Vector2d p0 = this.vportRt.ScrToWcs.MultiplyPoint(Vector2d.Zero);
            Vector2d p1 = this.vportRt.ScrToWcs.MultiplyPoint(new Vector2d(0, vp.Height));
            Vector2d p2 = this.vportRt.ScrToWcs.MultiplyPoint(new Vector2d(vp.Width, vp.Height));
            Vector2d p3 = this.vportRt.ScrToWcs.MultiplyPoint(new Vector2d(vp.Width, 0));

            Box2d box2d = new Box2d().ExpandByPoints(p0, p1, p2, p3);
            return box2d;
        }
        internal int DrawElements(SKCanvas canvas)
        {
            LcViewport vp = this.vportRt.Viewport;
            Box2d clipBox = this.GetWcsClipBox();
            LcDocument doc = this.docRt.Document;
            int dcount = 0;

            int count = vportRt.ActiveElementSet.Elements.Count;
            ElementCollection elements = vportRt.ActiveElementSet.Elements;

            //由于渲染线程和UI是不同的线程，这里需要考虑集合的动态变化
            for (int i = 0; i < count; i++)
            {
                if (i > (elements.Count - 1))
                {
                    break;
                }

                LcElement element = elements[i];
                if (!element.BoundingBox.IntersectWith(clipBox))
                {
                    continue;
                }

                //检查可以忽略绘制的元素
                if (CheckIgnored(element, i, vp.Scale)) continue;

                DrawElement(canvas, element);
                dcount++;
            }

            if (this.vportRt.DeactiveElementSet == null)
            {
                return dcount;
            }

            count = this.vportRt.DeactiveElementSet.Elements.Count;
            elements = this.vportRt.DeactiveElementSet.Elements;

            //由于渲染线程和UI是不同的线程，这里需要考虑集合的动态变化
            for (int i = 0; i < count; i++)
            {
                if (i > (elements.Count - 1)) break;
                LcElement element = elements[i];
                if (!element.BoundingBox.IntersectWith(clipBox)) continue;

                if (this.vportRt.IsRefEditing && this.vportRt.RefEditingObject.RefLinks[0] == element)
                {
                    element.RtStatus = ElementStatus.Normal;
                }
                else
                {
                    element.RtStatus = ElementStatus.Disabled;
                }

                //检查可以忽略绘制的元素
                if (this.CheckIgnored(element, i, vp.Scale))
                {
                    continue;
                }

                this.DrawElement(canvas, element);
                dcount++;
            }

            return dcount;
        }

        private bool CheckIgnored(LcElement element, int i, double scale)
        {
            if (element is LcRay || element is LcXLine)
            {
                return false;
            }
            //当元素量巨大时10-50万个，多数的元素已经被缩小到很小，视觉效果上无需都显示
            var zoomSize = Math.Max(element.BoundingBox.Width * scale, element.BoundingBox.Height * scale);
            if (zoomSize < 4 && i % 2 != 0)//1/2概率不显示
            {
                return true;
            }
            else if (zoomSize < 2 && i % 4 != 0)//3/4概率不显示
            {
                return true;
            }
            else if (zoomSize < 1 && i % 8 != 0)//7/8概率不显示
            {
                return true;
            }
            else if (zoomSize < 0.5 && i % 16 != 0)//15/16概率不显示
            {
                return true;
            }
            return false;

        }

        public void DrawElementGrips(SKCanvas canvas)
        {
            //多线程需要考虑动态变化
            var count = this.docRt.Action.ElementGrips.Count;
            for (var i = 0; i < count; i++)
            {
                if (i > this.docRt.Action.ElementGrips.Count - 1) break;
                DrawGrip(canvas, this.docRt.Action.ElementGrips[i]);
            }
            //Debug.Print(" Document: " + this.docRt.Document.FilePath);
        }
        public void DrawGrip(SKCanvas canvas, ControlGrip grip)
        {
            var wc = this.vportRt.ConvertWcsToScr(grip.Position).ToSKPoint();
            var color = Constants.GripColor;
            if (grip.IsHovered) color = HoveredColor;
            if (grip.IsSelected) color = SelectedColor;
            using (var pen = new SKPaint { Color = color, IsStroke = false })
            {
                canvas.DrawRect(wc.X - GripSize, wc.Y - GripSize, GripSize * 2, GripSize * 2, pen);
            }
        }
        private void DrawElement(SKCanvas canvas, LcElement element, Vector2d? offset = null)
        {
            var action = element.RtAction as ElementAction;
            if (offset == null) offset = Vector2d.Zero;
            action.SetViewport(this.vportRt).Draw(canvas, element, offset.Value);
        }


        public void DrawPasteElments(SKCanvas canvas, SKPoint pointerPos)
        {
            var wp = this.vportRt.ConvertScrToWcs(pointerPos.ToVector2d());
            var count = this.docRt.Action.PastingElements.Count;
            for (var i = 0; i < count; i++)
            {
                if (i > this.docRt.Action.PastingElements.Count - 1) break;
                DrawElement(canvas, this.docRt.Action.PastingElements[i], wp);
            }
        }
        public void DrawDragGrip(SKCanvas canvas)
        {
            try
            {
                var actionHandler = this.docRt.Action.SelectedGrip.Element.RtAction as ElementAction;
                Debug.Assert(actionHandler != null);

                actionHandler.SetViewport(this.vportRt).DrawDragGrip(canvas);
            }
            catch
            {
                // ignored
            }
        }

        /// <summary>
        /// 绘制拖拽中的元素
        /// </summary>
        /// <param name="doc"></param>
        /// <param name="canvas"></param>
        public void DrawDraggingSelection(SKCanvas canvas)
        {
            //var matrix= ElementDrawer.WorldToScrMatrix();
            //canvas.SetMatrix(matrix);

            //多线程需要考虑动态变化
            var count = this.docRt.Action.SelectedElements.Count;
            for (var i = 0; i < count; i++)
            {
                if (i > this.docRt.Action.SelectedElements.Count - 1)
                {
                    break;
                }

                var element = this.docRt.Action.SelectedElements[i];
                DrawElement(canvas, element, new Vector2d(this.docRt.Action.DragSelectionX, this.docRt.Action.DragSelectionY));
            }
        }

        internal void DrawSnapRefPoints(SKCanvas canvas)
        {
            var refPoints = this.vportRt.SnapRt.RefPoints;
            var hsize = SnapSettings.RefPointSize / 2;
            foreach (var rp in refPoints)
            {
                var wrp = this.vportRt.ConvertWcsToScr(rp.Point.Value).ToSKPoint();
                var left = new SKPoint(wrp.X - hsize, wrp.Y);
                var right = new SKPoint(wrp.X + hsize, wrp.Y);
                canvas.DrawLine(left, right, SnapSettings.RefPointPen);

                var top = new SKPoint(wrp.X, wrp.Y - hsize);
                var btm = new SKPoint(wrp.X, wrp.Y + hsize);
                canvas.DrawLine(top, btm, SnapSettings.RefPointPen);

            }
        }

        internal void DrawSnapRefCurves(SKCanvas canvas)
        {
        }

        internal void DrawSnapPoint(SKCanvas canvas)
        {
            var snapResult = this.vportRt.SnapRt.Current;
            var hsize = SnapSettings.SnapPointSize / 2;
            var srp = this.vportRt.ConvertWcsToScr(snapResult.SnapPoint.Value).ToSKPoint();
            var snapCurve = snapResult.Curves[0];
            switch (snapCurve.Type)
            {
                case SnapPointType.Endpoint:
                    {
                        var leftTop = new SKPoint(srp.X - hsize, srp.Y - hsize);
                        var rightBtm = new SKPoint(srp.X + hsize, srp.Y + hsize);
                        var rightTop = new SKPoint(srp.X + hsize, srp.Y - hsize);
                        var leftBtm = new SKPoint(srp.X - hsize, srp.Y + hsize);

                        canvas.DrawLine(leftTop, leftBtm, SnapSettings.SnapPointPen);
                        canvas.DrawLine(leftBtm, rightBtm, SnapSettings.SnapPointPen);
                        canvas.DrawLine(rightBtm, rightTop, SnapSettings.SnapPointPen);
                        canvas.DrawLine(rightTop, leftTop, SnapSettings.SnapPointPen);

                        break;
                    }
                case SnapPointType.Center:
                    {
                        var leftTop = new SKPoint(srp.X - hsize, srp.Y - hsize);
                        var rightBtm = new SKPoint(srp.X + hsize, srp.Y + hsize);
                        var rightTop = new SKPoint(srp.X + hsize, srp.Y - hsize);
                        var leftBtm = new SKPoint(srp.X - hsize, srp.Y + hsize);

                        canvas.DrawLine(leftTop, leftBtm, SnapSettings.SnapPointPen);
                        canvas.DrawLine(leftBtm, rightBtm, SnapSettings.SnapPointPen);
                        canvas.DrawLine(rightBtm, rightTop, SnapSettings.SnapPointPen);
                        canvas.DrawLine(rightTop, leftTop, SnapSettings.SnapPointPen);

                        break;
                    }
                case SnapPointType.Quadrant:
                    {
                        var leftTop = new SKPoint(srp.X - hsize, srp.Y - hsize);
                        var rightBtm = new SKPoint(srp.X + hsize, srp.Y + hsize);
                        var rightTop = new SKPoint(srp.X + hsize, srp.Y - hsize);
                        var leftBtm = new SKPoint(srp.X - hsize, srp.Y + hsize);

                        canvas.DrawLine(leftTop, leftBtm, SnapSettings.SnapPointPen);
                        canvas.DrawLine(leftBtm, rightBtm, SnapSettings.SnapPointPen);
                        canvas.DrawLine(rightBtm, rightTop, SnapSettings.SnapPointPen);
                        canvas.DrawLine(rightTop, leftTop, SnapSettings.SnapPointPen);

                        break;
                    }
                case SnapPointType.Midpoint:
                    {
                        var top = new SKPoint(srp.X, srp.Y - hsize);
                        var leftBtm = new SKPoint(srp.X - hsize*0.86f, srp.Y + hsize/2);
                        var rightBtm = new SKPoint(srp.X + hsize * 0.86f, srp.Y + hsize / 2);

                        canvas.DrawLine(top, leftBtm, SnapSettings.SnapPointPen);
                        canvas.DrawLine(leftBtm, rightBtm, SnapSettings.SnapPointPen);
                        canvas.DrawLine(rightBtm, top, SnapSettings.SnapPointPen);

                        break;
                    }
                case SnapPointType.Nearest:
                    {
                        var leftTop = new SKPoint(srp.X - hsize, srp.Y - hsize);
                        var rightBtm = new SKPoint(srp.X + hsize, srp.Y + hsize);
                        canvas.DrawLine(leftTop, rightBtm, SnapSettings.SnapPointPen);

                        var rightTop = new SKPoint(srp.X + hsize, srp.Y - hsize);
                        var leftBtm = new SKPoint(srp.X - hsize, srp.Y + hsize);
                        canvas.DrawLine(rightTop, leftBtm, SnapSettings.SnapPointPen);

                        canvas.DrawLine(leftTop, rightTop, SnapSettings.SnapPointPen);
                        canvas.DrawLine(leftBtm, rightBtm, SnapSettings.SnapPointPen);

                        break;
                    }
                case SnapPointType.ExtensionLine:
                    {
                        var leftTop = new SKPoint(srp.X - hsize, srp.Y-hsize);
                        var rightBtm = new SKPoint(srp.X + hsize, srp.Y+hsize);
                        canvas.DrawLine(leftTop, rightBtm, SnapSettings.SnapOuterPointPen);

                        var rightTop = new SKPoint(srp.X+hsize, srp.Y - hsize);
                        var leftBtm = new SKPoint(srp.X-hsize, srp.Y + hsize);
                        canvas.DrawLine(rightTop, leftBtm, SnapSettings.SnapOuterPointPen);

                        DrawExtensionLine(canvas,snapCurve, srp);
                        break;
                    }
            }
        }

        private void DrawExtensionLine(SKCanvas canvas, SnapRefCurve snapCurve, SKPoint srp)
        {
            var curve = snapCurve.Curve;
            switch(curve.Type)
            {
                case Curve2dType.Line2d:
                    {
                        var line = curve as Line2d;
                        var scrStart = this.vportRt.ConvertWcsToScr(line.Start).ToSKPoint();
                        var scrEnd = this.vportRt.ConvertWcsToScr(line.End).ToSKPoint();

                        var srpLenStart = SKPoint.Subtract(srp, scrStart).Length;
                        var srpLenEnd = SKPoint.Subtract(srp, scrEnd).Length;

                        if (srpLenStart > srpLenEnd)
                            canvas.DrawLine(srp, scrEnd, SnapSettings.SnapExtLinePen);
                        else
                            canvas.DrawLine(srp, scrStart, SnapSettings.SnapExtLinePen);
                        break;
                    }
            }
        }
    }


}
